Pregunta

Tengo estos objetos contenedores (llamémosles de contenedores) en una lista. Cada uno de estos contenedores objetos a su vez tiene un DataItem (o un derivado) en una lista. En un escenario típico de un usuario tendrá 15-20 Los objetos contenedor con cada DataItems 1000-5000. Luego hay algunos objetos DataMatcher que se pueden utilizar para diferentes tipos de búsquedas. Estos funcionan bien la mayoría (ya que tengo varios cientos de pruebas unitarias en ellos), pero con el fin de hacer que mi aplicación WPF siente ágil y sensible, que decidió que debería utilizar el ThreadPool para esta tarea. Por lo tanto tengo un DataItemCommandRunner que se ejecuta en un objeto contenedor, y básicamente realiza cada delegado en una lista que se necesita como un parámetro en cada DataItem a su vez; Yo uso el ThreadPool que hacer cola un hilo para cada contenedor, por lo que la búsqueda en teoría debería ser lo más eficiente posible en los ordenadores de varios núcleos, etc.

Esto se realiza básicamente en un DataItemUpdater clase que se ve algo como esto:

public class DataItemUpdater
{
    private Container ch;
    private IEnumerable<DataItemCommand> cmds;

    public DataItemUpdater(Container container, IEnumerable<DataItemCommand> commandList)
    {
        ch = container;
        cmds = commandList;
    }

    public void RunCommandsOnContainer(object useless)
    {
        Thread.CurrentThread.Priority = ThreadPriority.AboveNormal;
        foreach (DataItem di in ch.ItemList)
        {
            foreach (var cmd in cmds)
            {
                cmd(sh);
            }
        }
        //Console.WriteLine("Done running for {0}", ch.DisplayName);
    }
}

(El parámetro de objeto inútil para RunCommandsOnContainer es porque estoy experimentando con este con y sin el uso de hilos de rosca, y una de ellas requiere algún parámetro. Además, el establecimiento de la prioridad a AboveNormal es sólo un experimento también.)

Esto funciona bien para todos menos uno de los escenarios -. Cuando se utiliza el tipo de objeto AllWordsMatcher que buscará objetos DataItem que contienen todas las palabras que se busca (en oposición a cualquier palabra, frase exacta o expresiones regulares, por ejemplo)

Este es un objeto basado somestring.Contains(eachWord) bastante simple, respaldado por pruebas de unidad. Pero aquí radica cierta extrañeza cabelludo.

Cuando el RunCommandsOnContainer ejecuta utilizando hilos ThreadPool, le proporcione resultados dementes. Digamos que tiene una cadena como esta:

var someString = "123123123 - just some numbers";

Y corro esto:

var res = someString.Contains("data");

Cuando se ejecuta, esto va a devolver cierto bastante - He información de depuración que muestra lo va a devolver cierto para las cadenas vacías y otras cadenas que simplemente no contienen los datos. Además, será algunas veces return false incluso cuando la cadena contiene realmente los datos que se buscan.

El pateador en todo esto? ¿Por qué sospecho que el ThreadPool y no mi propio código?

Cuando ejecuto el RunCommandsOnContainer () de comandos para cada contenedor en mi hilo principal (es decir, el bloqueo de la interfaz de usuario y todo), funciona correctamente al 100% - cada vez! Nunca se encuentra algo que no debe, y nunca se salta nada debería hallarse.

Sin embargo, tan pronto como yo uso el ThreadPool, se inicia la búsqueda de un cantidad de artículos no debería, mientras que algunas veces no encontrar elementos que debería.

Me di cuenta que es un problema complejo (es doloroso tratando de depurar, eso es seguro!), Pero ninguna información sobre por qué y cómo solucionar este problema sería muy apreciada!

Gracias!

Rune

¿Fue útil?

Solución

Es un poco difícil de ver desde el fragmento que está enviando, pero a juzgar por los síntomas me gustaría ver en el AllWordsMatcher (busque estado estático). Si AllWordsMatcher es stateful También debe comprobar que está creando una nueva instancia para cada hilo.

De forma más general me vería en todas las instancias involucradas en el juego / proceso de búsqueda, específicamente a los objetos de trabajo que se utilizan cuando multihilo. A partir de la experiencia pasada, el problema suele radicar allí. (Es fácil mirar demasiado al objeto gráfico que representa el contenedor de datos de negocios / DataItem en este caso)

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top